Skip to content

构造函数继承(推荐 Es6,过时禁止使用的)

JavaScript 中的构造函数继承也称为借用构造函数、伪造对象或经典继承,它通过在子类构造函数内部调用父类构造函数来实现继承。

借助 apply()和 call()方法来改变对象的执行上下文,此方法为了解决原型中包含引用类型值所带来的问题。

  1. 构造函数继承

    • 构造函数继承是通过在子类的构造函数中调用父类的构造函数来实现继承。
    javascript
    function Parent() {
      this.name = "Parent";
    }
    
    function Child() {
      Parent.call(this); // 在子类的构造函数中调用父类的构造函数
    }
    var child = new Child();
    console.log(child.name); // 输出 "Parent"

缺陷例子

  • 无法继承父类原型上的方法:构造函数继承只能继承父类构造函数中定义的属性,而无法继承父类原型上的方法。这意味着丧失原型链,导致代码复用性降低。

  • 方法重复定义造成内存浪费:每次创建子类实例时,都会重新定义一遍父类构造函数内的属性和方法。这导致内存中存在多个相同的方法实例,造成内存浪费。

  • 无法传递参数:与原型链继承一样,构造函数继承也无法在创建子类实例时向父类构造函数传递参数,因为父类构造函数在子类构造函数内部被调用。

  • 无法实现多重继承:构造函数继承同样无法实现多重继承,因为它只能继承一个父类构造函数的属性和方法。

js
// 父类构造函数
function Parent(name) {
  this.name = name;
  this.colors = ["red", "blue", "green"];
}

// 父类方法
Parent.prototype.sayHello = function () {
  console.log("Hello, I'm " + this.name);
};

// 子类构造函数
function Child(name, age) {
  // 借用构造函数继承
  Parent.call(this, name);
  this.age = age;
}

// 创建子类实例
var child1 = new Child("Alice", 10);
var child2 = new Child("Bob", 12);

// 问题1:无法继承父类原型上的方法
child1.sayHello(); // 报错:child1.sayHello is not a function
console.log(child1 instanceof Parent); // 输出: false

// 问题2:方法重复定义造成内存浪费
console.log(child1.colors === child2.colors); // 输出: false

// 问题3:无法传递参数
console.log(child1.name); // 输出: Alice
console.log(child2.name); // 输出: Bob

// 问题4:无法实现多重继承,因为构造函数继承本身并不支持多重继承。